impl<'a, 'b> Source for GitSource<'a, 'b> {
fn update(&mut self) -> CargoResult<()> {
- let should_update = self.config.update_remotes() || {
- !self.remote.has_ref(&self.db_path, self.reference.as_slice()).is_ok()
- };
+ let actual_rev = self.remote.rev_for(&self.db_path,
+ self.reference.as_slice());
+ let should_update = self.config.update_remotes() || actual_rev.is_err();
let repo = if should_update {
try!(self.config.shell().status("Updating",
} else {
self.remote.db_at(&self.db_path)
};
+ let actual_rev = match actual_rev {
+ Ok(rev) => rev,
+ Err(..) => try!(repo.rev_for(self.reference.as_slice())),
+ };
- let checkout = try!(repo.copy_to(self.reference.as_slice(),
- &self.checkout_path));
+ try!(repo.copy_to(actual_rev.clone(), &self.checkout_path));
- let source_id = self.source_id.with_precise(checkout.get_rev().to_string());
+ let source_id = self.source_id.with_precise(actual_rev.to_string());
let path_source = PathSource::new(&self.checkout_path, &source_id);
self.path_source = Some(path_source);
fn fingerprint(&self, _pkg: &Package) -> CargoResult<String> {
let db = self.remote.db_at(&self.db_path);
- db.rev_for(self.reference.as_slice())
+ db.rev_for(self.reference.as_slice()).map(|r| r.to_string())
}
}
Other(String)
}
+#[deriving(PartialEq,Clone,Encodable)]
+pub struct GitRevision(String);
+
impl GitReference {
pub fn for_str<S: Str>(string: S) -> GitReference {
if string.as_slice() == "master" {
}
}
+impl Str for GitRevision {
+ fn as_slice(&self) -> &str {
+ let GitRevision(ref me) = *self;
+ me.as_slice()
+ }
+}
+
+impl Show for GitRevision {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ self.as_slice().fmt(f)
+ }
+}
macro_rules! git(
($config:expr, $($arg:expr),+) => (
pub struct GitCheckout {
database: GitDatabase,
location: Path,
- reference: GitReference,
- revision: String,
+ revision: GitRevision,
}
#[deriving(Encodable)]
pub struct EncodableGitCheckout {
database: GitDatabase,
location: String,
- reference: String,
revision: String,
}
EncodableGitCheckout {
database: self.database.clone(),
location: self.location.display().to_string(),
- reference: self.reference.to_string(),
revision: self.revision.to_string()
}.encode(s)
}
&self.location
}
- pub fn has_ref<S: Str>(&self, path: &Path, reference: S) -> CargoResult<()> {
- git_output!(*path, "rev-parse", reference.as_slice());
- Ok(())
+ pub fn rev_for<S: Str>(&self, path: &Path, reference: S)
+ -> CargoResult<GitRevision> {
+ Ok(GitRevision(git_output!(*path, "rev-parse", reference.as_slice())))
}
pub fn checkout(&self, into: &Path) -> CargoResult<GitDatabase> {
&self.path
}
- pub fn copy_to<S: Str>(&self, reference: S,
- dest: &Path) -> CargoResult<GitCheckout> {
+ pub fn copy_to(&self, rev: GitRevision, dest: &Path)
+ -> CargoResult<GitCheckout> {
let checkout = try!(GitCheckout::clone_into(dest, self.clone(),
- GitReference::for_str(reference.as_slice())));
+ rev.clone()));
- if self.remote.has_ref(dest, reference.as_slice()).is_err() {
- try!(checkout.fetch());
+ match self.remote.rev_for(dest, "HEAD") {
+ Ok(ref head) if rev == *head => return Ok(checkout),
+ _ => try!(checkout.fetch()),
}
- try!(checkout.reset(reference.as_slice()));
+
+ try!(checkout.reset());
try!(checkout.update_submodules());
Ok(checkout)
}
- pub fn rev_for<S: Str>(&self, reference: S) -> CargoResult<String> {
- Ok(git_output!(self.path, "rev-parse", reference.as_slice()))
+ pub fn rev_for<S: Str>(&self, reference: S) -> CargoResult<GitRevision> {
+ self.remote.rev_for(&self.path, reference)
}
+ pub fn has_ref<S: Str>(&self, reference: S) -> CargoResult<()> {
+ git_output!(self.path, "rev-parse", "--verify", reference.as_slice());
+ Ok(())
+ }
}
impl GitCheckout {
fn clone_into(into: &Path, database: GitDatabase,
- reference: GitReference) -> CargoResult<GitCheckout> {
- let revision = try!(database.rev_for(reference.as_slice()));
+ revision: GitRevision) -> CargoResult<GitCheckout> {
let checkout = GitCheckout {
location: into.clone(),
database: database,
- reference: reference,
revision: revision,
};
git!(dirname, "clone", "--no-checkout", "--quiet",
self.get_source(), &self.location);
+ try!(self.reset());
Ok(())
}
Ok(())
}
- fn reset(&self, revision: &str) -> CargoResult<()> {
- Ok(git!(self.location, "reset", "-q", "--hard", revision))
+ fn reset(&self) -> CargoResult<()> {
+ Ok(git!(self.location, "reset", "-q", "--hard",
+ self.revision.as_slice()))
}
fn update_submodules(&self) -> CargoResult<()> {